package cn.com.tarotframework.server.workflow.service.impl;

import cn.com.tarotframework.config.ThreadPoolTaskExecuteConfig;
import cn.com.tarotframework.server.workflow.eu.FlowEvents;
import cn.com.tarotframework.server.workflow.eu.FlowStatus;
import cn.com.tarotframework.server.workflow.po.FlowNode;
import cn.com.tarotframework.server.workflow.service.IFlowNodeService;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


@Service
public class FlowNodeStateServiceImpl implements IFlowNodeService {
    private final StateMachine<FlowStatus, FlowEvents> stateMachine;
    private final StateMachinePersister<FlowStatus, FlowEvents, FlowNode> persister;
    private final ThreadPoolTaskExecuteConfig executeConfig;

    public FlowNodeStateServiceImpl(StateMachinePersister<FlowStatus, FlowEvents, FlowNode> persister, StateMachine<FlowStatus, FlowEvents> stateMachine, ThreadPoolTaskExecuteConfig executeConfig) {
        this.persister = persister;
        this.stateMachine = stateMachine;
        this.executeConfig = executeConfig;
    }

    /**
     * 执行成功，由：EXECUTE_WAIT状态，更改为：EXECUTE_COMPLETE状态
     * @param flowNode 节点信息
     * @return FlowNode
     */
    @Async("node-flow-pool-0")
    @Override
    public CompletableFuture<FlowNode> executeComplete(FlowNode flowNode) {
        Message<FlowEvents> message = MessageBuilder.withPayload(FlowEvents.EXECUTE_COMPLETE).setHeader("flowNode", flowNode).build();
        if (!sendEvent(message, flowNode)) {
            System.out.println("---线程分组："+Thread.currentThread().getThreadGroup().getName()+"，线程名称："+Thread.currentThread().getName()+" 执行失败，当前状态："+flowNode.getStatus()+"，节点信息："+message.getHeaders().toString()+"， 状态机反馈信息【EXECUTE_WAIT--EXECUTE_COMPLETE】");
        }
        return CompletableFuture.completedFuture(flowNode);
    }

    /**
     * 执行成功，由：EXECUTE_WAIT状态，更改为：EXECUTE_COMPLETE状态
     * @param flowNodes 节点信息集合
     * @return FlowNode
     */
    @Async("node-flow-pool-0")
    @Override
    public CompletableFuture<List<FlowNode>> executeComplete(List<FlowNode> flowNodes) {
         flowNodes.forEach(this::executeComplete);
         return CompletableFuture.completedFuture(flowNodes);
    }

    /**
     * 执行失败，由：EXECUTE_WAIT状态，更改为：EXECUTE_ERROR状态
     * @param flowNode 节点信息
     * @return FlowNode
     */
    @Override
    public FlowNode executeFail(FlowNode flowNode) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Message<FlowEvents> message = MessageBuilder.withPayload(FlowEvents.EXECUTE_FAIL).setHeader("flowNode", flowNode).build();
        if (!sendEvent(message, flowNode)) {
            System.out.println("---线程分组："+Thread.currentThread().getThreadGroup().getName()+"，线程名称："+Thread.currentThread().getName()+" 执行失败，当前状态："+flowNode.getStatus()+"，节点信息："+message.getHeaders().toString()+"， 状态机反馈信息【EXECUTE_WAIT--EXECUTE_ERROR】，线程名称：" + Thread.currentThread().getName());
        }
        return flowNode;

    }

    /**
     * 未执行，由：EXECUTE_WAIT状态，更改为：EXECUTE_NOT状态
     * @param flowNode 节点信息
     * @return FlowNode
     */
    @Override
    public FlowNode executeStop(FlowNode flowNode) {
        Message<FlowEvents> message = MessageBuilder.withPayload(FlowEvents.EXECUTE_STOP).setHeader("flowNode", flowNode).build();
        if (!sendEvent(message, flowNode)) {
            System.out.println("---线程分组："+Thread.currentThread().getThreadGroup().getName()+"，线程名称："+Thread.currentThread().getName()+" 执行失败，当前状态："+flowNode.getStatus()+"，节点ID："+flowNode.getId()+"， 状态机反馈信息【EXECUTE_WAIT--EXECUTE_NOT】，线程名称：" + Thread.currentThread().getName());
        }
        return flowNode;
    }

    /**
     * 发送状态转换事件
     *
     * @param message 消息体
     * @param flowNode 节点信息
     * @return boolean
     */
    private synchronized boolean sendEvent(Message<FlowEvents> message, FlowNode flowNode) {
        boolean result = false;
        try {
            this.stateMachine.start();
            //尝试恢复状态机状态
            persister.restore(this.stateMachine, flowNode);
            //添加延迟用于线程安全测试
//            Thread.sleep(1000);
            result = this.stateMachine.sendEvent(message);
            //持久化状态机状态
            persister.persist(this.stateMachine, flowNode);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            this.stateMachine.stop();
        }
        return result;
    }

}
